package com.rpay.service.user.impl;

import com.google.common.collect.Lists;
import com.rpay.common.dto.mail.MailDTO;
import com.rpay.common.dto.user.UserIncomeDTO;
import com.rpay.common.dto.user.UserRippleDTO;
import com.rpay.common.enums.LevelEnum;
import com.rpay.common.util.DateUtil;
import com.rpay.common.util.LoggerUtil;
import com.rpay.common.vo.PageBean;
import com.rpay.dao.user.UserDao;
import com.rpay.dao.user.UserIncomeDao;
import com.rpay.dao.user.UserRippleDao;
import com.rpay.model.user.UserDO;
import com.rpay.model.user.UserIncomeDO;
import com.rpay.model.user.UserRippleDO;
import com.rpay.service.mail.IMailService;
import com.rpay.service.user.IUserIncomeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * Title：
 * Description
 *
 * @author fxg06 on 2018/5/13
 * @version 1.0
 */
@Service
public class UserIncomeServiceImpl implements IUserIncomeService {
    @Autowired
    private UserIncomeDao userIncomeDao;
    @Autowired
    private UserRippleDao userRippleDao;
    @Autowired
    private UserDao userDao;

    @Autowired
    private IMailService iMailService;

    @Override
    @Async
    public void updateUserIncome(Integer userId) {
        //获取前一天
        UserIncomeDO userIncome = new UserIncomeDO();
        BigDecimal rpayAmountBigDecimal = BigDecimal.ZERO;
        String date = DateUtil.formatDate(DateUtil.addDays(new Date(), -1));
        UserIncomeDO userIncomeDO = userIncomeDao.selectByUserId(userId, date);
        if (userIncomeDO == null || userIncomeDO.getId() == null) {
            return;
        }
        try {
            List<UserRippleDO> rippleDOList = userRippleDao.selectUserRipples(userId, date);
            userIncome.setAchievementHistory(userIncomeDO.getAchievementHistory());
            if (!CollectionUtils.isEmpty(rippleDOList)) {
                //id不为null，表示该用户这天有收益
                if (userIncomeDO.getId() != null) {
                    //等级大于0 才去计算指数
                    if (userIncomeDO.getLevel() > 0) {
                        //合约指数，非周末才有
                        if (!DateUtil.isRestDay(date)) {
                            BigDecimal total = BigDecimal.ZERO;
                            if (!CollectionUtils.isEmpty(rippleDOList)) {
                                for (UserRippleDO rippleDO : rippleDOList) {
                                    BigDecimal tempBg = rippleDO.getInvestAmount().multiply(rippleDO.getPrice()).multiply(userIncomeDO.getIncomeRate()).divide(new BigDecimal(100));
                                    total = total.add(tempBg);
                                }
                                userIncomeDO.setContractIncome(total);
                                rpayAmountBigDecimal = rpayAmountBigDecimal.add(total);
                            }
                        }
                        //团队指数
                        BigDecimal teamIndex = userIncomeDO.getTeamAchievement().multiply(userIncomeDO.getTeamRate()).divide(new BigDecimal(100));
                        userIncomeDO.setAchievementIncome(teamIndex);
                        rpayAmountBigDecimal = rpayAmountBigDecimal.add(teamIndex);
                        //全网指数
                        BigDecimal rateBigDecimal;
                        BigDecimal achievement = userIncomeDO.getAchievement();
                        BigDecimal achievementHistory = userIncomeDO.getAchievementHistory();
                        if (achievementHistory.compareTo(BigDecimal.ZERO) == 0) {
                            achievementHistory = BigDecimal.ONE;
                        }
                        BigDecimal bg = achievement.divide(achievementHistory, 10, BigDecimal.ROUND_HALF_UP);
                        if (bg.compareTo(new BigDecimal("0.02")) == -1) {
                            rateBigDecimal = userIncomeDO.getLowerRate();
                        } else if (bg.compareTo(new BigDecimal("0.1")) == 1) {
                            rateBigDecimal = userIncomeDO.getHighRate();
                        } else {
                            rateBigDecimal = userIncomeDO.getMiddleRate();
                        }
                        userIncomeDO.setWholeIncome(achievementHistory.multiply(rateBigDecimal).divide(new BigDecimal("100")));
                        rpayAmountBigDecimal = rpayAmountBigDecimal.add(userIncomeDO.getWholeIncome());
                        //会员等级等于6，表示该会员为股东，更新分红指数
                        if (userIncomeDO.getLevel() == 6) {
                            int count = userDao.selectCountByLevel(6);
                            BigDecimal sumBigDecimal = userIncomeDao.selectInvestCount(date);
                            if (sumBigDecimal == null) {
                                sumBigDecimal = BigDecimal.ZERO;
                            }
                            BigDecimal bonusRate = userIncomeDO.getBonusRate();
                            if (bonusRate == null) {
                                bonusRate = BigDecimal.ZERO;
                            }
                            bonusRate = bonusRate.divide(new BigDecimal(100));
                            userIncomeDO.setBonusIncome(sumBigDecimal.multiply(bonusRate).divide(new BigDecimal(count), 10, BigDecimal.ROUND_HALF_UP));
                            rpayAmountBigDecimal = rpayAmountBigDecimal.add(userIncomeDO.getBonusIncome());
                        }
                        userIncomeDao.updateUserIncome(userIncomeDO);
                    }
                    //直推、逆推
                    rpayAmountBigDecimal = rpayAmountBigDecimal.add(userIncomeDO.getRecommendIncome());
                    rpayAmountBigDecimal = rpayAmountBigDecimal.add(userIncomeDO.getRecommendedIncome());
                    LoggerUtil.info("userId==========>" + userIncomeDO.getUserId());
                    LoggerUtil.info("level==========>" + userIncomeDO.getLevel());
                    LoggerUtil.info("contractIncome==========>" + userIncomeDO.getContractIncome());
                    LoggerUtil.info("recommendedIncome==========>" + userIncomeDO.getRecommendedIncome());
                    LoggerUtil.info("recommendIncome==========>" + userIncomeDO.getRecommendIncome());
                    LoggerUtil.info("achievementIncome==========>" + userIncomeDO.getAchievementIncome());
                    LoggerUtil.info("wholeIncome==========>" + userIncomeDO.getWholeIncome());
                    LoggerUtil.info("bonusIncome==========>" + userIncomeDO.getBonusIncome());
                }
            }
            userIncome.setUserId(userId);
            userIncome.setLevel(userIncomeDO.getNewLevel());
            userIncome.setDate(new Date());
            userIncomeDao.insertUserIncome(userIncome);

            //更新用户的rpay余额
            UserDO userDO = userDao.selectUserById(userId);
            userDO.setRpayAmount(rpayAmountBigDecimal.add(userDO.getRpayAmount()));
            userDao.update(userDO);
        } catch (Exception e) {
            e.printStackTrace();
            LoggerUtil.error("userId {} update index failed, time{}", userId, date);
            MailDTO mailDTO = new MailDTO();
            mailDTO.setReceiver("97383102@qq.com");
            mailDTO.setSubject("用户id为" + userId + "更新指数失败，失败时间" + date);
            mailDTO.setContent("失败原因：" + e.toString());
            iMailService.send(mailDTO);
        }
    }

    @Override
    @Async
    public void updateUserAchievement(UserRippleDTO rippleDTO) {
        BigDecimal achievement = rippleDTO.getInvestAmount().multiply(rippleDTO.getPrice());
        List<UserIncomeDO> list = userIncomeDao.selectAll(rippleDTO.getUserId());
        List<UserIncomeDO> incomeList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        UserIncomeDO userIncome = null;
        for (UserIncomeDO userIncomeDO : list) {
            //找到自己
            if (rippleDTO.getUserId().equals(userIncomeDO.getUserId())) {
                userIncome = userIncomeDO;
                break;
            }
        }
        if (userIncome != null) {
            for (UserIncomeDO userIncomeDO : list) {
                //父级，计算直推和逆推，同时计算父级的团队收益及历史收益
                if (userIncomeDO.getUserId().equals(userIncome.getParentId())) {
                    BigDecimal total = userRippleDao.selectTotalByUserId(userIncomeDO.getUserId());
                    BigDecimal amount = rippleDTO.getInvestAmount();
                    if (total.compareTo(amount) == -1) {
                        amount = total;
                    }
                    //父级获取直推
                    BigDecimal recommend = userIncomeDO.getRecommendIncome();
                    if (recommend == null) {
                        recommend = BigDecimal.ZERO;
                    }
                    recommend = recommend.add(amount.multiply(userIncomeDO.getRecommendRate()).multiply(rippleDTO.getPrice()).divide(new BigDecimal(100)));
                    userIncomeDO.setRecommendIncome(recommend);
                    //自己获取逆推
                    BigDecimal recommended = userIncome.getRecommendedIncome();
                    if (recommended == null) {
                        recommended = BigDecimal.ZERO;
                    }
                    recommended = recommended.add(amount.multiply(userIncome.getRecommendedRate()).multiply(rippleDTO.getPrice()).divide(new BigDecimal(100)));
                    userIncome.setRecommendedIncome(recommended);
                    //如果自己的等级比父级的等级大，收益减半
                    if (userIncome.getLevel() >= userIncomeDO.getLevel()) {
                        achievement = achievement.divide(new BigDecimal(2));
                    }
                    userIncomeDO.setAchievementHistory(userIncomeDO.getAchievementHistory().add(achievement));
                    userIncomeDO.setAchievement(userIncomeDO.getAchievement().add(achievement));
                    incomeList.add(userIncome);
                    incomeList.add(userIncomeDO);

                    incomeList = getIncomeList(userIncomeDO.getLevel(), userIncomeDO.getParentId(), achievement, list, incomeList, 2);
                    break;
                }
            }
        }
        List<UserIncomeDO> insertList = Lists.newArrayList();
        List<UserIncomeDO> updateList = Lists.newArrayList();
        for (UserIncomeDO userIncomeDO : incomeList) {
            if (userIncomeDO.getId() == null) {
                insertList.add(userIncomeDO);
            } else {
                updateList.add(userIncomeDO);
            }
        }
        if (!CollectionUtils.isEmpty(updateList)) {
            userIncomeDao.updateAll(updateList);
        }
        if (!CollectionUtils.isEmpty(insertList)) {
            userIncomeDao.insertAll(insertList);
        }

    }


    @Override
    public UserIncomeDTO statistics(Integer userId) {
        UserIncomeDO userIncomeDO = userIncomeDao.selectByStatistics(userId, null);
        UserIncomeDO yesterdayIncome = userIncomeDao.selectByStatistics(userId, DateUtil.formatDate(DateUtil.addDays(new Date(), -1)));
        UserIncomeDTO userIncomeDTO = convertDOToDTO(userIncomeDO);
        if (userIncomeDO.getLargessIncome() != null) {
            userIncomeDTO.setLargessIncome(userIncomeDO.getLargessIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
        } else {
            userIncomeDTO.setLargessIncome(userIncomeDO.getLargessIncome());
        }
        if (userIncomeDO.getWithdrawIncome() != null) {
            userIncomeDTO.setWithdrawIncome(userIncomeDO.getWithdrawIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
        } else {
            userIncomeDTO.setWithdrawIncome(userIncomeDO.getWithdrawIncome());
        }


        BigDecimal bigDecimal = userIncomeDO.getContractIncome()
                .add(userIncomeDO.getRecommendIncome())
                .add(userIncomeDO.getRecommendedIncome())
                .add(userIncomeDO.getAchievementIncome())
                .add(userIncomeDO.getWholeIncome())
                .add(userIncomeDO.getBonusIncome())
                .add(userIncomeDO.getLargessIncome());

        BigDecimal yesterdayBigDecimal = yesterdayIncome.getContractIncome()
                .add(yesterdayIncome.getRecommendIncome())
                .add(yesterdayIncome.getRecommendedIncome())
                .add(yesterdayIncome.getAchievementIncome())
                .add(yesterdayIncome.getWholeIncome())
                .add(yesterdayIncome.getBonusIncome())
                .add(yesterdayIncome.getLargessIncome());

        userIncomeDTO.setTotalIncome(bigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP));
        userIncomeDTO.setYesterdayIncome(yesterdayBigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP));

        return userIncomeDTO;
    }


    @Override
    public PageBean<UserIncomeDTO> listUserIncome(Integer userId, String beginDate, String endDate, Integer pageIndex, Integer pageSize) {
        PageBean pageBean = new PageBean(pageIndex, pageSize);
        int count = userIncomeDao.selectCount(userId, beginDate, endDate);
        pageBean.setCount(count);
        if (count > 0) {
            int pageOffset = pageSize * (pageIndex - 1);
            List<UserIncomeDO> userIncomeDOS = userIncomeDao.selectUserIncomes(userId, beginDate, endDate, pageOffset, pageSize);
            List<UserIncomeDTO> list = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(userIncomeDOS)) {
                for (UserIncomeDO userIncomeDO : userIncomeDOS) {
                    list.add(convertDOToDTO(userIncomeDO));
                }
                pageBean.setList(list);
            }
        }
        return pageBean;
    }

    private List<UserIncomeDO> getIncomeList(Integer level, Integer parentId, BigDecimal achievement, List<UserIncomeDO> list, List<UserIncomeDO> incomeList, int count) {
        for (UserIncomeDO userIncomeDO : list) {
            //找到父级
            if (userIncomeDO.getUserId().equals(parentId)) {
//                //如果自己的等级比父级的等级大，收益减半
//                if (level >= userIncomeDO.getLevel()) {
//                    achievement = achievement.divide(new BigDecimal(2));
//                } else {
//                    //获取最大level
//                    level = userIncomeDO.getLevel();
//                }
                userIncomeDO.setAchievement(userIncomeDO.getAchievement().add(achievement));
                userIncomeDO.setAchievementHistory(userIncomeDO.getAchievementHistory().add(achievement));
                //判断等级对应计算的代数
                if (LevelEnum.getGenerateion(userIncomeDO.getLevel()) >= count) {
                    userIncomeDO.setTeamAchievement(userIncomeDO.getTeamAchievement().add(achievement));
                }
                //代数加1
                count++;
                incomeList.add(userIncomeDO);
                incomeList = getIncomeList(level, userIncomeDO.getParentId(), achievement, list, incomeList, count);
                break;
            }
        }
        return incomeList;
    }

    private UserIncomeDTO convertDOToDTO(UserIncomeDO userIncomeDO) {
        UserIncomeDTO userIncomeDTO = new UserIncomeDTO();
        if (userIncomeDO != null) {
            if (userIncomeDO.getContractIncome() != null) {
                userIncomeDTO.setContractIncome(userIncomeDO.getContractIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setContractIncome(userIncomeDO.getContractIncome());
            }
            if (userIncomeDO.getRecommendIncome() != null) {
                userIncomeDTO.setRecommendIncome(userIncomeDO.getRecommendIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setRecommendIncome(userIncomeDO.getRecommendIncome());
            }
            if (userIncomeDO.getRecommendedIncome() != null) {
                userIncomeDTO.setRecommendedIncome(userIncomeDO.getRecommendedIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setRecommendedIncome(userIncomeDO.getRecommendedIncome());
            }
            if (userIncomeDO.getAchievementIncome() != null) {
                userIncomeDTO.setAchievementIncome(userIncomeDO.getAchievementIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setAchievementIncome(userIncomeDO.getAchievementIncome());
            }
            if (userIncomeDO.getBonusIncome() != null) {
                userIncomeDTO.setBonusIncome(userIncomeDO.getBonusIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setBonusIncome(userIncomeDO.getBonusIncome());
            }
            if (userIncomeDO.getWholeIncome() != null) {
                userIncomeDTO.setWholeIncome(userIncomeDO.getWholeIncome().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setWholeIncome(userIncomeDO.getWholeIncome());
            }
            if (userIncomeDO.getAchievement() != null) {
                userIncomeDTO.setAchievement(userIncomeDO.getAchievement().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setAchievement(userIncomeDO.getAchievement());
            }
            if (userIncomeDO.getAchievementHistory() != null) {
                userIncomeDTO.setAchievementHistory(userIncomeDO.getAchievementHistory().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setAchievementHistory(userIncomeDO.getAchievementHistory());
            }
            if (userIncomeDO.getTeamAchievement() != null) {
                userIncomeDTO.setTeamAchievement(userIncomeDO.getTeamAchievement().setScale(4, BigDecimal.ROUND_HALF_UP));
            } else {
                userIncomeDTO.setTeamAchievement(userIncomeDO.getTeamAchievement());
            }
            if (userIncomeDO.getDate() != null) {
                userIncomeDTO.setDate(DateUtil.formatDate(userIncomeDO.getDate()));
            }
        }
        return userIncomeDTO;
    }

}
